package com.test.resolver;

import com.test.handler.NamespaceHandler;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 默认的命名空间处理器解析器，用于根据命名空间URI解析出对应的命名空间处理器
 */
public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver{

    // 默认的命名空间处理器映射文件位置
    public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";

    // 存储命名空间URI与处理器类名的映射关系
    private final Map<String,String> handlerMappings = new HashMap<>();

    // 存储已实例化的命名空间处理器，避免重复创建
    private final Map<String, NamespaceHandler> handlerCache = new HashMap<>();

    /**
     * 默认构造函数，使用默认的映射文件位置
     */
    public DefaultNamespaceHandlerResolver() {
        this(DEFAULT_HANDLER_MAPPINGS_LOCATION);
    }

    /**
     * 构造函数，允许指定命名空间处理器映射文件的位置
     * @param handlerMappingsLocation 映射文件的位置
     */
    public DefaultNamespaceHandlerResolver(String handlerMappingsLocation) {
        loadHandlerMappings(handlerMappingsLocation);
    }

    /**
     * 加载命名空间处理器映射
     * @param handlerMappingsLocation 映射文件的位置
     */
    private void loadHandlerMappings(String handlerMappingsLocation) {
        try {
            Properties mappings = new Properties();
            InputStream is = this.getClass().getClassLoader().getResourceAsStream(handlerMappingsLocation);
            if (is != null){
                try{
                    mappings.load(is);
                }finally {
                    is.close();
                }
            }

            for (Map.Entry<Object, Object> entry : mappings.entrySet()){
                String namespaceUri = (String) entry.getKey();
                String handlerClassName = (String) entry.getValue();
                handlerMappings.put(namespaceUri, handlerClassName);
            }
        }catch (Exception e){
            throw new IllegalStateException("无法加载命名空间处理器映射：" + handlerMappingsLocation, e);
        }
    }

    /**
     * 根据命名空间URI解析并返回对应的命名空间处理器
     * @param namespaceUri 命名空间URI
     * @return 对应的命名空间处理器，如果找不到则返回null
     */
    @Override
    public NamespaceHandler resolve(String namespaceUri) {
        NamespaceHandler handler = handlerCache.get(namespaceUri);
        if (handler != null){
            return handler;
        }

        String handlerClassName = handlerMappings.get(namespaceUri);
        if (handlerClassName == null){
            return null;
        }

        try{
            Class<?> handlerClass = Class.forName(handlerClassName);
            if (!NamespaceHandler.class.isAssignableFrom(handlerClass)){
                throw new IllegalStateException("类 [" + handlerClassName + "] 不是NamespaceHandler 的实现");
            }

            handler = (NamespaceHandler) handlerClass.newInstance();

            handler.init();
            handlerCache.put(namespaceUri, handler);
            return handler;
        }catch (ClassNotFoundException e){
            throw new IllegalStateException("找不到命名空间处理器类：" + handlerClassName, e);
        }catch (InstantiationException e){
            throw new IllegalStateException("无法实例化命名空间处理器类：" + handlerClassName, e);
        }catch (IllegalAccessException e){
            throw new IllegalStateException("无法访问命名空间处理器类：" + handlerClassName, e);
        }
    }
}

